'use strict';
let PDFDocment = require('pdfkit');
let Enumerable = require('linq');
let Request = require('request');
const SIZES = require('./PDFSizes');

/**
 *PDF渲染基类
 *
 * @class BaseRender
 */
class BaseRender {
	constructor(data, style) {
		this._data = data;
		this._style = style;
		this._pageSetting = this._getDefaultSetting(style);
		this._doc = new PDFDocment(this._pageSetting);
		this._doc.registerFont('normal', './fonts/SimSun.ttf');
		this._doc.registerFont('blod', './fonts/SimSum-Blod.ttf');
		this._doc.registerFont('thin', './fonts/STSONG.TTF');
	}

	/**
	 *渲染响应
	 *
	 * @returns
	 * @param {*} res
	 * @memberof BaseRender
	 */
	async render(res) {
		try {
			await this._requestData();
			this._render();
			this._doc.end();
			this._doc.pipe(res);
		} catch (ex) {
			res.end(`PDF render error: ${ex}`);
		}
	}

	/**
	 *数据请求
	 *
	 * @returns
	 * @memberof BaseRender
	 */
	async _requestData() {
		let data = this._data;
		if (!data.detailParams) return;
		let detailData = await this._post({
			url: data.detailDataUrl,
			body: JSON.stringify(data.detailParams),
			headers: {
				Cookie: data.cookie
			}
		});
		if (detailData && detailData.itemList) {
			data.detailData = detailData;
		}
	}

	/**
	 *POST请求
	 *
	 * @param {*} options
	 * @returns
	 * @memberof BaseRender
	 */
	async _post(options) {
		let newOptions = {
			...options,
			method: 'POST',
			headers: {
				...options.headers,
				'content-type': 'application/json'
			}
		};
		return await new Promise((resolve, reject) => {
			Request(newOptions, (err, res, body) => {
				let data = {};
				try {
					if (!err) data = JSON.parse(body);
				} catch (ex) {}
				resolve(data);
			});
		});
	}

	/**
	 *获取默认配置
	 *
	 * @param {*} byStyle
	 * @returns
	 * @memberof BaseRender
	 */
	_getDefaultSetting(byStyle) {
		let data = this._data;
		let style = this._style;
		let date = new Date();
		let pageSetting = {
			size: 'A4',
			layout: 'portrait',
			bufferPages: true,
			margin: 0,
			tableMaxHeight: 560, // 表格最大高度
			tableMargin: 40, // 表格边距
			tableTop: 110, // 表格顶部高度
			fontSize: 12, //  默认字体大小
			reportCount: 1, // 单页报表数
			showPageNum: false, // 是否显示页码
			info: {
				Producer: 'PDFRender',
				Creator: 'PDFRender',
				Title: data.reportName,
				Author: '章鱼侠云打印',
				Keywords: '云打印 PDF打印',
				ModDate: date,
				CreationDate: date
			}
		};
		let tempPageSetting = byStyle ? style.pageSetting : data.pageSetting;
		if (tempPageSetting) {
			pageSetting.size = tempPageSetting.size || pageSetting.size;
			pageSetting.layout = tempPageSetting.layout || pageSetting.layout;
			pageSetting.tableMaxHeight = tempPageSetting.tableMaxHeight || pageSetting.tableMaxHeight;
			pageSetting.tableMargin = tempPageSetting.tableMargin || pageSetting.tableMargin;
			pageSetting.tableTop = tempPageSetting.tableTop || pageSetting.tableTop;
			pageSetting.fontSize = tempPageSetting.fontSize || pageSetting.fontSize;
			pageSetting.reportCount = tempPageSetting.reportCount || pageSetting.reportCount;
			pageSetting.showPageNum = tempPageSetting.showPageNum || pageSetting.showPageNum;
		}
		if (Array.isArray(pageSetting.size)) {
			pageSetting.width = pageSetting.size[0];
			pageSetting.height = pageSetting.size[1];
		} else {
			pageSetting.width = SIZES[pageSetting.size][0];
			pageSetting.height = SIZES[pageSetting.size][1];
		}
		return pageSetting;
	}

	/**
	 *深拷贝
	 *
	 * @param {*} o
	 * @returns
	 * @memberof PDFRender
	 */
	_deepCopy(o) {
		if (o instanceof Array) {
			var n = [];
			for (var i = 0; i < o.length; ++i) {
				n[i] = this._deepCopy(o[i]);
			}
			return n;
		} else if (o instanceof Function) {
			var n = new Function('return ' + o.toString())();
			return n;
		} else if (o instanceof Object) {
			var n = {};
			for (var i in o) {
				n[i] = this._deepCopy(o[i]);
			}
			return n;
		} else {
			return o;
		}
	}

	/**
	 *渲染方框
	 *
	 * @param {*} rect
	 * @memberof BaseRender
	 */
	_renderRect(rect) {
		let doc = this._doc;
		doc.lineWidth(1)
			.moveTo(rect.left, rect.top)
			.lineTo(rect.left, rect.top + rect.height)
			.lineTo(rect.left + rect.width, rect.top + rect.height)
			.lineTo(rect.left + rect.width, rect.top)
			.lineTo(rect.left, rect.top)
			.stroke();
	}

	/**
	 *渲染文本
	 *
	 * @param {*} text
	 * @param {*} options
	 * @memberof BaseRender
	 */
	_renderText(text, options = {}) {
		let doc = this._doc;
		let pageSetting = this._pageSetting;
		let fontName = options.name || 'normal';
		let fontSize = options.size || pageSetting.fontSize;
		let valign = options.valign || 'top';
		let newOptions = {
			lineBreak: true,
			width: options.width,
			align: options.align || 'left',
			height: options.height
		};
		// 如果垂直居中
		if (options.height && valign != 'top') {
			let textHeight = this._getTextHeight(text, newOptions);
			if (textHeight < options.height) {
				if (valign == 'center') {
					let temp = (options.height - textHeight) / 2 - 5;
					options.top += temp < 0 ? 0 : temp;
				} else if (valign == 'bottom') {
					options.top += options.height - textHeight - 5;
				}
			}
		}
		if (options.isFixedRowHeight) {
			newOptions.height = options.height;
		}
		doc.font(fontName)
			.fontSize(fontSize)
			.text(text, options.left, options.top, newOptions);
	}

	/**
	 *渲染方框及文本
	 *
	 * @param {*} text
	 * @param {*} options
	 * @memberof BaseRender
	 */
	_renderTextAndRect(text, options = {}) {
		let doc = this._doc;
		this._renderRect({
			left: options.left,
			top: options.top,
			width: options.width,
			height: options.height
		});
		this._renderText(text, {
			left: options.left + 5,
			top: options.top + 5,
			width: options.width - 10,
			align: options.align || 'left',
			name: options.name || 'normal',
			valign: options.valign,
			height: options.height || 0,
			isFixedRowHeight: options.isFixedRowHeight || false,
			size: options.size
		});
	}

	/**
	 *获取文本宽度
	 *
	 * @param {*} text
	 * @param {*} options
	 * @returns
	 * @memberof BaseRender
	 */
	_getTextWidth(text, options = {}) {
		let doc = this._doc;
		let pageSetting = this._pageSetting;
		let fontName = options.name || 'normal';
		let fontSize = options.size || pageSetting.fontSize;
		let width = doc
			.font(fontName)
			.fontSize(fontSize)
			.widthOfString(text);
		return width;
	}

	/**
	 *获取文本高度
	 *
	 * @param {*} text
	 * @param {*} options
	 * @returns
	 * @memberof BaseRender
	 */
	_getTextHeight(text, options = {}) {
		let doc = this._doc;
		let pageSetting = this._pageSetting;
		let fontName = options.name || 'normal';
		let fontSize = options.size || pageSetting.fontSize;
		let height = doc
			.font(fontName)
			.fontSize(fontSize)
			.heightOfString(text, {
				lineBreak: true,
				width: options.width,
				align: options.align || 'left'
			});
		return height;
	}

	/**
	 *是否为主表字段
	 *
	 * @param {*} control
	 * @returns
	 * @memberof BaseRender
	 */
	_isMasterField(control) {
		return control.text.substr(0, 1) == '@';
	}

	/**
	 *是否为从表字段
	 *
	 * @param {*} control
	 * @returns
	 * @memberof BaseRender
	 */
	_isDetailField(control) {
		return control.text.substr(0, 1) == '#';
	}

	/**
	 *是否为合计字段
	 *
	 * @param {*} control
	 * @returns
	 * @memberof BaseRender
	 */
	_isSumField(control) {
		return control.text.substr(0, 1) == '^';
	}

	/**
	 *是否为数据行
	 *
	 * @param {*} row
	 * @returns
	 * @memberof BaseRender
	 */
	_isDetailFieldRow(row) {
		for (let i = 0; i < row.cells.length; i++) {
			let cell = row.cells[i];
			if (this._isDetailField(cell)) return true;
		}
		return false;
	}

	/**
	 *获取数据字段名
	 *
	 * @param {*} control
	 * @returns
	 * @memberof PDFRender
	 */
	_getDetailFieldName(control) {
		if (this._isDetailField(control)) return control.text.substr(1, control.text.length);
		return '';
	}

	/**
	 *获取数据字段
	 *
	 * @param {*} control
	 * @returns
	 * @memberof PDFRender
	 */
	_getDetailField(control) {
		let data = this._data;
		let detailName = this._getDetailFieldName(control);
		if (detailName == '') return null;
		let detailField = Enumerable.from(data.detailFields).firstOrDefault(field => field.name == detailName);
		control.detailField = detailField;
		return detailField;
	}

	/**
	 *获取数据字段值
	 *
	 * @param {*} control
	 * @param {*} dataItem
	 * @returns
	 * @memberof PDFRender
	 */
	_getDetailFieldValue(control, dataItem) {
		let detailField = control.detailField || this._getDetailField(control);
		return detailField ? dataItem[detailField.dataField] : control.text;
	}

	/**
	 *获取主表字段值
	 *
	 * @param {*} control
	 * @param {*} tempData
	 * @returns
	 * @memberof PDFRender
	 */
	_getMasterFieldValue(control, tempData) {
		let value = control.text;
		if (this._isMasterField(control)) {
			let masterField = this._getMasterField(control);
			value = tempData && tempData.data ? tempData.data[masterField.dataField] : masterField.value;
		} else if (this._isSumField(control)) {
			value = this._getSumFieldValue(control);
		}
		if (control.showCaption) {
			value = `${control.name}：${value}`;
		}
		return value;
	}

	/**
	 *获取统计字段
	 *
	 * @param {*} control
	 * @memberof BaseRender
	 */
	_getSumFieldValue(control) {
		let value = '';
		let datailSumTexts = this._data.datailSumTexts;
		if (datailSumTexts && Array.isArray(datailSumTexts)) {
			let name = control.text.substr(1, control.text.length);
			let text=Enumerable.from(datailSumTexts).firstOrDefault(text => text.name === name);
			if(text) value=text.sumText;
		}
		return value;
	}

	/**
	 *通过text获取主表字段名
	 *
	 * @param {*} control
	 * @returns
	 * @memberof PDFRender
	 */
	_getMasterField(control) {
		let data = this._data;
		let masterField = new Object();
		Enumerable.from(data.masterFields).forEach(item => {
			if (item.name !== control.name) return;
			masterField.name = item.name;
			masterField.caption = item.name;
			masterField.dataField = item.dataField;
			masterField.value = item.value;
		});
		return masterField;
	}
}

exports = module.exports = BaseRender;